/**
 * 
 */
package Verifier;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * This class is the main class of the verifier. It contains the main entry point of the 
 * verifier, interprets the arguments and runs the verifier.
 * 
 * @author Moshe Baavur
 *
 */
public class VerifierMain {
	/**
	 * The main entry point of the verifier - this function parses the arguments and starts the verifier accordingly.
	 * The return value would be 0 if the proof is accepted, and 1 otherwise.
	 * 
	 * @param args the arguments of the command line - should point to the protocol file and to the proofs directory, and may include the optional parameter - verbose.
	 */
	public static void main(String[] args) {
		// first, check the given arguments
		String[] verifierArgs = new String[5];
		int argsIndex = 0;
		boolean verboseMode = false;
		// find if we need to use verbose mode and save all other arguments except for the verbose flag
		for (int i = 0; i < args.length; i++) {
			if ((!verboseMode) && (0 == args[i].compareToIgnoreCase("-v"))) {
				verboseMode = true;
				continue;
			}
			verifierArgs[argsIndex++] = args[i];
		}
		
		// check if the arguments are as expected
		if ((2 != argsIndex) && (5 != argsIndex)) {
			printHelp();
			System.exit(1);
		}
		// create a verifier object to verify the proofs
		Verifier mainVerifier;
		if (2 == argsIndex)
			mainVerifier = new Verifier(verifierArgs[0], verifierArgs[1], verboseMode);
		else
			mainVerifier = new Verifier(verifierArgs[0], verifierArgs[1], verifierArgs[2], verifierArgs[3], verifierArgs[4], verboseMode);

		printStartTime(verboseMode);
		// check the proofs
		if (false == mainVerifier.RunTest()) {
			// the proofs are not accepted - return non-zero exit code
			printEndTime(verboseMode, false);
			System.exit(1);
		}
		// the proof is accepted - return zero as an exit code
		printEndTime(verboseMode, true);
		System.exit(0);
	}
	
	// print a help message for the user to know how to run the application, if the number of arguments is wrong
	private static void printHelp() {
		System.out.println("Usage: verifier [-v] protInfo.xml roProof [pkey ciphertexts plaintexts]");
		System.out.println("Verifies a run of the Verificatum");
		System.out.println();
		System.out.println("Options and arguments: ");
		System.out.println("  -v               Verbose mode - print messages to the screen");
		System.out.println("  protInfo.xml     The path to the protocol info xml file");
		System.out.println("  roProof          The path to the roProof folder");
		System.out.println("  pkey             The path to the public key file - this parameter is optional, but if used,");
		System.out.println("                   it should point to a text file and the ciphertexts and plaintexts are required");
		System.out.println("  ciphertexts      The path to the cipher texts file - this parameter is optional, but if used,");
		System.out.println("                   it should point to a text file and the pkey and plaintexts are required");
		System.out.println("  plaintexts       The path to the plain texts file - this parameter is optional, but if used,");
		System.out.println("                   it should point to a text file and the pkey and ciphertexts are required");
		System.out.println();
	}
	
	private static DateFormat dateFormat;
	private static Date startDate;
	
	// prints a starting message - this only happens if we should run in verbose mode
	private static void printStartTime(boolean showTime) {
		if (false == showTime)
			return;
		// print the start date
		dateFormat = new SimpleDateFormat("HH:mm:ss dd/MM/yyyy");
		startDate = new Date();
		System.out.println(dateFormat.format(startDate) + " : ===== Test Started =====");
	}
	
	// prints an ending message and counts the time since the test started - this only happens if we should run in verbose mode
	private static void printEndTime(boolean showTime, boolean result) {
		if (false == showTime)
			return;
		// print the end date
		Date endDate = new Date();
		System.out.println(dateFormat.format(endDate) + " : Test Finished");
		System.out.println();
		// print the result of the test
		if (result)
			System.out.println(dateFormat.format(endDate) + " : ===== Test Succeeded =====");
		else
			System.out.println(dateFormat.format(endDate) + " : ===== Test Failed =====");
		System.out.println();
		// create two calendars to find the actual time it took to finish the test
		Calendar calendar1 = Calendar.getInstance();
		calendar1.setTime(startDate);
		Calendar calendar2 = Calendar.getInstance();
		calendar2.setTime(endDate);
		long totalTimeInSecs = (calendar2.getTimeInMillis() - calendar1.getTimeInMillis()) / 1000;
		int hours = (int)((totalTimeInSecs / 60) / 60) % 24;
		int minutes = (int)(totalTimeInSecs / 60) % 60;
		int seconds = (int)totalTimeInSecs % 60;
		System.out.println("The test has finished after " + String.format("%02d Hours, %02d Minutes and %02d Seconds", hours, minutes, seconds));
	}
}
